package cn.dglydrpy.study.j2ee.mq.rabbitmq.producer;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException;
/*
生产者发送消息的流程:
1. 生产者连接RabbitMQ，建立TCP连接( Connection)，开启信道（Channel） 2. 生产者声明一个Exchange（交换器），并设置相关属性，比如交换器类型、是否持久化等
3. 生产者声明一个队列井设置相关属性，比如是否排他、是否持久化、是否自动删除等
4. 生产者通过 bindingKey （绑定Key）将交换器和队列绑定（ binding ）起来
5. 生产者发送消息至RabbitMQ Broker，其中包含 routingKey （路由键）、交换器等信息
6. 相应的交换器根据接收到的 routingKey 查找相匹配的队列。
7. 如果找到，则将从生产者发送过来的消息存入相应的队列中。
8. 如果没有找到，则根据生产者配置的属性选择丢弃还是回退给生产者
9. 关闭信道。
10. 关闭连接。
*/
public class HelloProducer {
    public static void main(String[] args) throws IOException, TimeoutException, KeyManagementException, NoSuchAlgorithmException, URISyntaxException {
    	
// 创建连接工厂,方式一:    	
        // 获取连接工厂
//        ConnectionFactory factory = new ConnectionFactory();
//        建立的连接是否要求自动恢复
//        factory.setAutomaticRecoveryEnabled(false);
//        ExecutorService executor = Executors.
//        factory.setSharedExecutor(executor);
//
//        // 设置主机名 hostname 或者 主机ip
//        factory.setHost("192.168.80.131");
//        // 设置虚拟主机名称  /在url中的转义字符 %2f
//        factory.setVirtualHost("/");
//        // 用户名
//        factory.setUsername("admin");
//        // 密码
//        factory.setPassword("147258aaaaa");
//        // amqp的端口号
//        factory.setPort(5672);

// 创建连接工厂,方式二: 
        ConnectionFactory factory = new ConnectionFactory();
        factory.setUri("amqp://admin:147258aaaaa@192.168.80.131:5672/%2f");

        // 建立TCP连接
        Connection connection = factory.newConnection();
        // 获取通道
        Channel channel = connection.createChannel();

        // 声明消息队列:queue使用主机的内存和磁盘存储，受到内存和磁盘空间的限制   
        // 消息队列名称
        // 是否是持久化的
        // 是否是排他的，为true表示仅当前channel可使用
        // 是否是自动删除的
        // 消息队列的属性信息。使用默认值；
        channel.queueDeclare("queue.hello", false, false, true, null);

        // 声明交换器
        // 交换器的名称
        // 交换器的类型
        // 交换器是否是持久化的
        // 交换器是否是自动删除的
        // 交换器的属性map集合
        channel.exchangeDeclare("ex.hello", BuiltinExchangeType.DIRECT, false, false, null);
        
        // 将交换器和消息队列绑定，并指定路由键
        channel.queueBind("queue.hello", "ex.hello", "key.hello");
      
        // 发送消息
        // 交换器的名字
        // 该消息的路由键
        // 该消息的属性BasicProperties对象
        // 消息的字节数组
        for(int i=0;i<15;i++) {
        	 channel.basicPublish("ex.hello", "key.hello", null, ("hello world " + i + "!").getBytes());
        }
       
        // 关闭通道
        channel.close();
        // 关闭连接
        connection.close();
    }
}
